package com.starlink.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.hutool.core.convert.Convert;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.PageHelper;
import com.starlink.context.SessionContext;
import com.starlink.model.domain.StarPaintRegisterDO;
import com.starlink.model.request.PointsAcquireBillRequest;
import com.starlink.service.PointsService;
import com.starlink.service.StarPaintRegisterService;
import org.springframework.data.domain.Pageable;
import com.starlink.common.utils.AssertUtil;
import com.starlink.model.dtomapper.StarPaintDtoMapper;
import com.starlink.model.domain.StarPaintDO;
import com.starlink.mapper.StarPaintMapper;
import com.starlink.model.request.StarPaintRequest;
import com.starlink.service.StarPaintService;
import com.starlink.model.util.StarPaintConvert;
import com.starlink.model.vo.StarPaintVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.starlink.common.enums.ActionTypeEum.JOIN_STAR_PAINT_ACTIVITY;
import static com.starlink.common.enums.ActionTypeEum.STAR_PAINT_ACTIVITY_CANCEL;
import static com.starlink.utils.PageUtils.getOrderBy;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author zhanghong
 */
@Service
public class StarPaintServiceImpl extends ServiceImpl<StarPaintMapper, StarPaintDO> implements StarPaintService {
    @Autowired
    private StarPaintMapper starPaintMapper;
    @Autowired
    private StarPaintRegisterService starPaintRegisterService;
    @Autowired
    private PointsService pointsService;

    @Override
    public StarPaintVO getByKey(long id) {
        StarPaintVO starPaintVO = StarPaintDtoMapper.INSTANCE.do2VO(getById(id));
        AssertUtil.assertNotNull(starPaintVO, "活动id不存在");
        // 如果是小程序用户登录获取详情查询是否已经报名
        Long wechatUserId = SessionContext.getWechatUserId();
        if (wechatUserId != null) {
            Long count = starPaintRegisterService.lambdaQuery().eq(StarPaintRegisterDO::getStarPaintId, starPaintVO.getId()).count();
            starPaintVO.setRegisterCount(count);

            StarPaintRegisterDO one = starPaintRegisterService.lambdaQuery()
                    .eq(StarPaintRegisterDO::getStarPaintId, starPaintVO.getId())
                    .eq(StarPaintRegisterDO::getUserId, wechatUserId)
                    .last("limit 1")
                    .one();
            if (one != null) {
                starPaintVO.setIsRegister(1);
            }
        }
        return starPaintVO;
    }

    @Override
    public PageInfo<StarPaintVO> pageQuery(Pageable pageable,StarPaintRequest request) {
        PageHelper.startPage(request.getPageNum(), request.getPageSize(), getOrderBy(pageable.getSort())).setReasonable(true);
        List<StarPaintDO> list = starPaintMapper.listQuery(request);
        List<StarPaintVO> starPaintVOList = StarPaintConvert.buildStarPaintVoList(list);
        return new PageInfo(starPaintVOList);
    }

    @Override
    public List<StarPaintVO> listQuery(StarPaintRequest request) {
        List<StarPaintDO> list = starPaintMapper.selectDOList(StarPaintDtoMapper.INSTANCE.request2DO(request));
        List<StarPaintVO> starPaintVOS = StarPaintConvert.buildStarPaintVoList(list);
        // 查询报名人数
        for (StarPaintVO starPaintVO : starPaintVOS) {
            Long count = starPaintRegisterService.lambdaQuery().eq(StarPaintRegisterDO::getStarPaintId, starPaintVO.getId()).count();
            starPaintVO.setRegisterCount(count);

            StarPaintRegisterDO one = starPaintRegisterService.lambdaQuery()
                    .eq(StarPaintRegisterDO::getStarPaintId, starPaintVO.getId())
                    .eq(StarPaintRegisterDO::getUserId, SessionContext.getWechatUserId())
                    .last("limit 1")
                    .one();
            if (one != null) {
                starPaintVO.setIsRegister(1);
            }
        }
        return starPaintVOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(StarPaintRequest request) {
        save(StarPaintDtoMapper.INSTANCE.request2DO(request));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByKey(StarPaintRequest request) {
        AssertUtil.assertNotNull(request.getId(), "id不能为空");
        saveOrUpdate(StarPaintDtoMapper.INSTANCE.request2DO(request));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateStatus(StarPaintRequest request) {
        AssertUtil.assertNotNull(request.getId(), "id不能为空");
        AssertUtil.assertNotNull(request.getStatus(), "活动上下架状态不能为空");
        StarPaintDO starPaintDO = starPaintMapper.selectDOById(request.getId());
        AssertUtil.assertNotNull(starPaintDO, "活动不存在");
        if (starPaintDO.getStatus().equals(0) && request.getStatus().equals(1)) {
            // 从下架 -> 上架
            AssertUtil.assertFalse(starPaintDO.getActivityEndTime().getTime() < new Date().getTime(), "已结束的活动不能再次上架");
            AssertUtil.assertTrue(starPaintDO.getManualOff() == 0 ,"已下架的活动不支持再次上架");
        }
        StarPaintDO entity = StarPaintDtoMapper.INSTANCE.request2DO(request);
        if (starPaintDO.getStatus().equals(1) && request.getStatus().equals(0)) {
            // 从上架 -> 下架
            if (new Date().getTime() < starPaintDO.getActivityEndTime().getTime()) {
                // 提前手动下架（退还用户报名积分）
                // 查询报名记录
                List<StarPaintRegisterDO> list = starPaintRegisterService.lambdaQuery()
                        .eq(StarPaintRegisterDO::getStarPaintId, starPaintDO.getId())
                        .list();
                for (StarPaintRegisterDO starPaintRegisterDO : list) {
                    PointsAcquireBillRequest billRequest = new PointsAcquireBillRequest();
                    billRequest.setUserId(starPaintRegisterDO.getUserId());
                    billRequest.setTitle(STAR_PAINT_ACTIVITY_CANCEL.getType());
                    billRequest.setAcquireMode(STAR_PAINT_ACTIVITY_CANCEL.getType());
                    billRequest.setAcquirePoint(starPaintDO.getConsumePoints());
                    pointsService.addPoint(billRequest);
                }
            }
            entity.setManualOff(1);
        }
        saveOrUpdate(entity);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteDOByIds(String ids) {
        starPaintMapper.deleteDOByIds(Convert.toStrArray(ids));
        return true;
    }
}
